//
//  TFICloudDownloadView.m
//  MyCoolAnimationCollectionProject
//
//  Created by TFAppleWork-Summer on 2017/1/19.
//  Copyright © 2017年 TFAppleWork-Summer. All rights reserved.
//

#import "TFICloudDownloadView.h"
#import "TFICloudDownloadViewAnimationInfoObject.h"

static NSString *kICloudDownloadViewLineToPointAnimationKey = @"ICloudDownloadViewLineToPointAnimation";

static NSString *kICloudDownloadViewArrowToPointAnimationKey = @"ICloudDownloadViewArrowToPointAnimation";

static NSString *kICloudDownloadViewLoadingAnimationKey = @"ICloudDownloadViewLoadingAnimation";

static NSString *kICloudDownloadViewSuccessAnimationKey = @"ICloudDownloadViewSuccessAnimation";

static NSString *kICloudDownloadViewSuccessByCircleAnimationKey = @"ICloudDownloadViewSuccessByCircleAnimation";

@interface TFICloudDownloadView ()<CAAnimationDelegate>

@property (nonatomic, assign) CAShapeLayer *circleLayer;
//加载圈
@property (nonatomic, strong) CAShapeLayer *loadingCircleLayer;
//箭头
@property (nonatomic, strong) CAShapeLayer *arrowLayer;
//竖线
@property (nonatomic, strong) CAShapeLayer *verticalLineLayer;
//云layer
@property (nonatomic, strong) CAShapeLayer *cloudLayer;
//云进度layer
@property (nonatomic, strong) CAShapeLayer *cloudProgressLayer;
//进度圆环宽度
@property (nonatomic, assign) CGFloat progressWidth;
//线的高度
@property (nonatomic, assign) CGFloat lineWidth;
//内容的tintColor
@property (nonatomic, strong) UIColor *contentTintColor;

@property (nonatomic, strong) TFICloudDownloadViewAnimationInfoObject *animationInfoObj;

@property (nonatomic, copy) TFICloudDownloadAnimationCompletionBlock startCompletionBlock;

@property (nonatomic, copy) TFICloudDownloadAnimationCompletionBlock successCompletionBlock;

@end

@implementation TFICloudDownloadView

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        self.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.6];
        _contentTintColor = [UIColor whiteColor];
        _lineWidth = 2.0;
        _progressWidth = 2.0;
    }
    return self;
}

- (void)drawRect:(CGRect)rect {
    [super drawRect:rect];
    _animationInfoObj = [[TFICloudDownloadViewAnimationInfoObject alloc] initWithFrame:rect cloudSize:self.cloudSize];

    [self.layer addSublayer:self.circleLayer];
    [self.layer addSublayer:self.loadingCircleLayer];
    [self.layer addSublayer:self.cloudLayer];
    [self.layer addSublayer:self.cloudProgressLayer];
    [self.layer addSublayer:self.verticalLineLayer];
    [self.layer addSublayer:self.arrowLayer];
}

- (void)startAnimationWithCompletion:(TFICloudDownloadAnimationCompletionBlock)completion {
    _startCompletionBlock = completion;
    [self recoverOriginalState];

    CABasicAnimation *lineToPointAnimation = [_animationInfoObj lineToPointAnimation];
    lineToPointAnimation.delegate = self;
    [self.verticalLineLayer addAnimation:lineToPointAnimation forKey:kICloudDownloadViewLineToPointAnimationKey];
    CAKeyframeAnimation *arrowToPointAnimation = [_animationInfoObj arrowToPointAnimation];
    arrowToPointAnimation.delegate = self;
    [self.arrowLayer addAnimation:arrowToPointAnimation forKey:kICloudDownloadViewArrowToPointAnimationKey];
}

- (void)didMoveToSuperview {
    [super didMoveToSuperview];
    if (!self.superview) {
        [_verticalLineLayer removeAllAnimations];
        [_arrowLayer removeAllAnimations];
        [_loadingCircleLayer removeAllAnimations];
        [_cloudProgressLayer removeAllAnimations];
        [_circleLayer removeAllAnimations];
    }
}

- (void)successAnimationWithCompletion:(TFICloudDownloadAnimationCompletionBlock)completion {
    _successCompletionBlock = completion;
    _cloudLayer.hidden = YES;
    _cloudLayer.strokeEnd = 0.0;
    _progress = 0.0;
    //移除加载动画
    [_loadingCircleLayer removeAnimationForKey:kICloudDownloadViewLoadingAnimationKey];
    _loadingCircleLayer.hidden = YES;
    //显示成功动画
    CABasicAnimation *successAnimation = [_animationInfoObj cloudToSuccessAnimation];
    successAnimation.delegate = self;
    [self.cloudProgressLayer addAnimation:successAnimation forKey:kICloudDownloadViewSuccessAnimationKey];
    [self.circleLayer addAnimation:[_animationInfoObj successByCircleAnimation] forKey:kICloudDownloadViewSuccessByCircleAnimationKey];
}

- (void)failAnimation {
    _arrowLayer.hidden = NO;
    _verticalLineLayer.hidden = NO;
    _cloudProgressLayer.strokeEnd = 0.0;
    //移除加载动画
    [_loadingCircleLayer removeAnimationForKey:kICloudDownloadViewLoadingAnimationKey];
    _loadingCircleLayer.hidden = YES;
    [_arrowLayer removeAnimationForKey:kICloudDownloadViewArrowToPointAnimationKey];
    [_verticalLineLayer removeAnimationForKey:kICloudDownloadViewLineToPointAnimationKey];
    _arrowLayer.path = _animationInfoObj.reloadArrowPath.CGPath;
    _verticalLineLayer.path = _animationInfoObj.reloadCirclePath.CGPath;
}

- (void)recoverOriginalState {
    _arrowLayer.hidden = NO;
    _arrowLayer.path = _animationInfoObj.arrowStartPath.CGPath;
    _cloudLayer.hidden = NO;
    _verticalLineLayer.hidden = NO;
    _verticalLineLayer.path = _animationInfoObj.verticalLineStartPath.CGPath;
    _cloudProgressLayer.strokeEnd = 0.0;
    [_verticalLineLayer removeAnimationForKey:kICloudDownloadViewLineToPointAnimationKey];
    [_arrowLayer removeAnimationForKey:kICloudDownloadViewArrowToPointAnimationKey];
    [_cloudProgressLayer removeAnimationForKey:kICloudDownloadViewSuccessAnimationKey];
    [_circleLayer removeAnimationForKey:kICloudDownloadViewSuccessByCircleAnimationKey];
}


#pragma mark - CAAnimationDelegate

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
    
    if (flag && [self.arrowLayer animationForKey:kICloudDownloadViewArrowToPointAnimationKey] == anim) {
        _arrowLayer.hidden = YES;
        _loadingCircleLayer.hidden = NO;
        CAKeyframeAnimation *loadingAnimation = [_animationInfoObj circleLoadingAnimation];
        [_loadingCircleLayer addAnimation:loadingAnimation forKey:kICloudDownloadViewLoadingAnimationKey];
        if (_startCompletionBlock) {
            _startCompletionBlock(self);
        }
    }
    else if (flag && [self.verticalLineLayer animationForKey:kICloudDownloadViewLineToPointAnimationKey] == anim) {
        //实时更新状态
        _verticalLineLayer.hidden = YES;
    }
    else if (flag && [self.cloudProgressLayer animationForKey:kICloudDownloadViewSuccessAnimationKey] == anim) {
        if (_successCompletionBlock) {
            _successCompletionBlock(self);
        }
    }
}

#pragma mark - lazy load.

- (void)setProgress:(float)progress {
    _progress = progress;
    if (![_loadingCircleLayer animationForKey:kICloudDownloadViewLoadingAnimationKey]) {
        _loadingCircleLayer.hidden = NO;
        CAKeyframeAnimation *loadingAnimation = [_animationInfoObj circleLoadingAnimation];
        [_loadingCircleLayer addAnimation:loadingAnimation forKey:kICloudDownloadViewLoadingAnimationKey];
        //设置对应的layer的状态
        _arrowLayer.path = _animationInfoObj.arrowCloudStartPath.CGPath;
        _arrowLayer.hidden = YES;

        _verticalLineLayer.path = _animationInfoObj.verticalLineEndPath.CGPath;
        _verticalLineLayer.hidden = YES;
    }
    _cloudProgressLayer.strokeEnd = progress;
}

- (CAShapeLayer *)circleLayer {
    if (!_circleLayer) {
        _circleLayer = [self _getDefaultCircleLayer];
        CGFloat width = CGRectGetWidth(self.frame);
        CGFloat height = CGRectGetHeight(self.frame);
        _circleLayer.path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(width*0.5, height*0.5) radius:self.cloudSize.width*0.5 startAngle:-M_PI_2 endAngle:M_PI_2*3 clockwise:YES].CGPath;
        _circleLayer.strokeEnd = 0.0;
        _circleLayer.strokeColor = _contentTintColor.CGColor;
    }
    return _circleLayer;
}

- (CAShapeLayer *)loadingCircleLayer {
    if (!_loadingCircleLayer) {
        _loadingCircleLayer = [CAShapeLayer layer];
        CGFloat width = CGRectGetWidth(self.frame);
        CGFloat height = CGRectGetHeight(self.frame);
        CGRect circleLayerFrame = CGRectMake((width-self.cloudSize.width)*0.5, (height-self.cloudSize.height)*0.5, self.cloudSize.width, self.cloudSize.height);
        _loadingCircleLayer.frame = circleLayerFrame;

        CAShapeLayer *circleLayer = [self _getDefaultCircleLayer];
        CGFloat inset = _progressWidth*0.5;
        circleLayer.frame = CGRectMake(inset, inset, CGRectGetWidth(circleLayerFrame)-_progressWidth, CGRectGetHeight(circleLayerFrame) - _progressWidth);
        UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.cloudSize.width*0.5, self.cloudSize.height*0.5) radius:self.cloudSize.width*0.5 startAngle:M_PI_2 endAngle:M_PI_2*3 clockwise:YES];
        circleLayer.path = path.CGPath;
        circleLayer.strokeColor = _contentTintColor.CGColor;
        circleLayer.strokeEnd = 1.0;
    
        CAGradientLayer *gradientLayer = [CAGradientLayer layer];
        gradientLayer.frame = CGRectMake(0, 0, self.cloudSize.width, self.cloudSize.height);
        gradientLayer.colors = @[(__bridge id)[[UIColor whiteColor] colorWithAlphaComponent:0.85].CGColor,
                                 (__bridge id)[[UIColor whiteColor] colorWithAlphaComponent:0.40].CGColor,
                                 (__bridge id)[[UIColor whiteColor] colorWithAlphaComponent:0.2].CGColor,
                                 (__bridge id)[[UIColor whiteColor] colorWithAlphaComponent:0.0].CGColor,
                                 ];
        gradientLayer.startPoint = CGPointMake(0.0, 0.0);
        gradientLayer.endPoint = CGPointMake(0.0, 1.0);
        gradientLayer.locations = @[@(0.08),@(0.15),@(0.30),@(0.55)];
        [_loadingCircleLayer addSublayer:gradientLayer];
        _loadingCircleLayer.mask = circleLayer;
        _loadingCircleLayer.lineCap = kCALineCapRound;
        _loadingCircleLayer.hidden = YES;
    }
    return _loadingCircleLayer;
}

- (CAShapeLayer *)_getDefaultCircleLayer {
    CAShapeLayer *layer = [CAShapeLayer layer];
    CGFloat inset = _progressWidth*0.5;
    layer.frame = CGRectMake(inset, inset, CGRectGetWidth(self.frame)-_progressWidth, CGRectGetHeight(self.frame)-_progressWidth);
    layer.lineWidth = _progressWidth;
    layer.fillColor = [UIColor clearColor].CGColor;
    layer.lineCap = kCALineCapRound;
    return layer;
}

- (CAShapeLayer *)arrowLayer {
    if (!_arrowLayer) {
        _arrowLayer = [CAShapeLayer layer];
        _arrowLayer.frame = self.bounds;
        _arrowLayer.strokeColor = _contentTintColor.CGColor;
        _arrowLayer.lineCap = kCALineCapRound;
        _arrowLayer.lineWidth = _lineWidth;
        _arrowLayer.fillColor = [UIColor clearColor].CGColor;
        _arrowLayer.lineJoin = kCALineJoinRound;
        _arrowLayer.path = _animationInfoObj.arrowStartPath.CGPath;
    }
    return _arrowLayer;
}

- (CAShapeLayer *)verticalLineLayer {
    if (!_verticalLineLayer) {
        _verticalLineLayer = [CAShapeLayer layer];
        _verticalLineLayer.frame = self.bounds;
        _verticalLineLayer.strokeColor = _contentTintColor.CGColor;
        _verticalLineLayer.lineCap = kCALineCapRound;
        _verticalLineLayer.lineWidth = _lineWidth;
        _verticalLineLayer.fillColor = [UIColor clearColor].CGColor;
        _verticalLineLayer.path = _animationInfoObj.verticalLineStartPath.CGPath;
    }
    return _verticalLineLayer;
}

- (CAShapeLayer *)cloudLayer {
    if (!_cloudLayer) {
        _cloudLayer = [CAShapeLayer layer];
        _cloudLayer.frame = self.bounds;
        _cloudLayer.lineWidth = _lineWidth;
        _cloudLayer.strokeColor = [_contentTintColor colorWithAlphaComponent:0.3].CGColor;
        _cloudLayer.fillColor = [UIColor clearColor].CGColor;
        _cloudLayer.path = _animationInfoObj.cloudPath.CGPath;
    }
    return _cloudLayer;
}

- (CAShapeLayer *)cloudProgressLayer {
    if (!_cloudProgressLayer) {
        _cloudProgressLayer = [CAShapeLayer layer];
        _cloudProgressLayer.frame = self.bounds;
        _cloudProgressLayer.lineWidth = _lineWidth;
        _cloudProgressLayer.strokeColor = _contentTintColor.CGColor;
        _cloudProgressLayer.fillColor = [UIColor clearColor].CGColor;
        _cloudProgressLayer.path = _cloudLayer.path;
        _cloudProgressLayer.strokeEnd = 0.0;
    }
    return _cloudProgressLayer;
}


/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // Drawing code
}
*/

@end


